import json
import logging
import sys
from functools import reduce

from typing import Iterator, List

sys.path.extend(["F:/ML/BNC", "D:/BNC", "/www/wwwroot/BNC"])

from WebServer.blog.NewInterface.NOT_INIT import CodeTagRelationMapper, parse_sqlalchemy_model_2_dict, TagRenameMapper, \
    ReplayMapper, SearchCTRKWMapper, TagStatusMapper, set_sqlalchemy_model_values
from WebServer.blog.NewInterface.tp import parse_excel_2_obj

from django.http import JsonResponse
from rest_framework import status
from rest_framework.views import APIView
from Utils.Funcc import parse_date_from_s, NOT_SPILT_DATE_FORMAT, BASE_DATE_FORMAT, reformat_s_date_s, DateEncoder, \
    parse_rp_2_dicts, parse_rp_2_rows
from WebServer.blog.Utils.Fnc import wrapper_res_dict, generate_message_dict_4_fail, from_query_set_get_model, \
    paginator_sql
from WebServer.blog.models import *
from WebServer.blog.models import DBSession_mysql

log = logging.getLogger(__name__)


class CTRBatchApiView(APIView):
    def put(self, request):
        session = DBSession_mysql()
        try:
            CodeTagRelationMapper.insert_relation_batch(request.data.get("data"), session)
            res = {}
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()
    # def patch(self, request):
    #     # 进行前处理
    #     session = DBSession_mysql()
    #     try:
    #         db_res = CodeTagRelationMapper.pre_parse_relation_batch(request.data.get("pre_data"))
    #         res = {}
    #         res['data'] = db_res
    #     except Exception as e:
    #         log.exception(e)
    #         return JsonResponse(generate_message_dict_4_fail(500, e.args))
    #     else:
    #         return JsonResponse(wrapper_res_dict(res, False))
    #     finally:
    #         session.commit()
    #


class CTRFileUploadApiView(APIView):
    def post(self, request):
        res = {}
        try:
            res['data'] = parse_sqlalchemy_model_2_dict(parse_excel_2_obj(request.data['file']))
        except Exception as e:
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))


class CTRApiView(APIView):
    def get(self, request):
        session = DBSession_mysql()
        try:
            # db_res = CodeTagRelationMapper.show_relation_code_list(session)
            # db_res = parse_sqlalchemy_model_2_dict(db_res)
            # js_ = json.dumps(db_res, cls=DateEncoder)
            res = {}
            # res['data'] = db_res
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def put(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            # session = DBSession_mysql()
            # date_s = request.data.get("cur_date")
            # date_ = reformat_s_date_s(date_s, BASE_DATE_FORMAT,output_format=NOT_SPILT_DATE_FORMAT)
            # 插入股票关系数据，默认设置为启用
            obj = from_query_set_get_model(request.data, CodeTagRelation,
                                           need_cols=['id', 'code', 'tag', 'start_date', 'end_date', 'enable'])
            # 网页接口提供默认值
            # obj = parse__2_sac_model(request.data, CodeTagRelation)
            # obj.enable = True
            CodeTagRelationMapper.insert_or_update_relation(obj, session)
            # js_ = json.dumps(db_res,  cls=DateEncoder)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def delete(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            CodeTagRelationMapper.taggle_ctr_status(request.data.get("id"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def patch(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            CodeTagRelationMapper.taggle_ctr_fresh_status(request.data.get("id"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

class TagRenameListApiView(APIView):
    def get(self, request):
        session = DBSession_mysql()
        res = {}
        try:
            db_res=SearchCTRKWMapper.search_tags((request.query_params.getlist("kw",[""])))
            # db_res = TagRenameMapper.only_to_tag(session,request.query_params.get("kw",""))
            res['data'] = db_res
        except Exception as e:
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.close()

class TagRenameSubApiView(APIView):
    def get(self, request):
        session = DBSession_mysql()
        res = {}
        try:
            parent_tag = request.query_params.get("kw")
            db_res = TagRenameMapper.child_tags(parent_tag, session)
            res['data'] = db_res
        except Exception as e:
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.close()

    def post(self,request):
        session = DBSession_mysql()
        res = {}
        try:
            parent_tag = request.data.get("tag")
            sub_tag = request.data.get("sub_tag")
            TagRenameMapper.insert_or_update_tag_rename(TagRename(origin=sub_tag, to=parent_tag,fresh=NOT_FRESH,source="手动新建标签映射"),session,rename_enable=ENABLE,tag_enable=ENABLE)
            session.commit()
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.close()

    def delete(self,request):
        session = DBSession_mysql()
        res = {}
        try:
            parent_tag = request.query_params.get("tag")
            sub_tag = request.query_params.get("sub_tag")
            tr=TagRename(origin=sub_tag,to=parent_tag)
            TagRenameMapper.delete_tag_rename_by_uk(tr,session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            session.commit()
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.close()

class CTRBatchNewApiView(APIView):
    def post(self, request):
        session = DBSession_mysql()
        res = {}
        try:
            parent_tag = request.data.get("tag")
            rela_codes = request.data.get("rela_codes")
            for rela_code_ in rela_codes:
                code_ = rela_code_['code']
                rela_code_.setdefault('reason','手动新建关系')
                rela_code_.setdefault("link",'')
                rela_code_.setdefault("source",'从其他关系中进行复制')

                ctr = CodeTagRelation(code=rela_code_['code'],tag=parent_tag,enable=ENABLE,reason=rela_code_['reason'],link=rela_code_['link'],source=rela_code_['source'])
                CodeTagRelationMapper.insert_or_update_relation(ctr,session, enable_tag=ENABLE, tag_to=parent_tag, rename_enable=ENABLE)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

class TagRenameApiView(APIView):
    def get(self, request):
        session = DBSession_mysql()
        try:
            db_res = TagRenameMapper.list(session)
            db_res = parse_sqlalchemy_model_2_dict(db_res, )
            res = {}
            res['data'] = db_res
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def put(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            tr_obj = from_query_set_get_model(request.data, TagRename)
            TagRenameMapper.insert_or_update_tag_rename(tr_obj, session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def delete(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            TagRenameMapper.toggle_tag_rename_status(request.data.get("id"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def patch(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            TagRenameMapper.toggle_tag_map_fresh(request.data.get("id"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()


class TagRenameDeleteApiView(APIView):
    def delete(self, request):
        # 进行前处理
        session = DBSession_mysql()
        res = {}
        try:
            TagRenameMapper.delete_tag_rename(request.data.get("id"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()


class TagRenameBatchApiView(APIView):
    def post(self, request):
        """
        用于前处理
        """
        res = {}
        session = DBSession_mysql()
        try:
            res = TagRenameMapper.pre_parse_replay_batch(request.data.get("pks"), request.data.get("item"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))

        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def put(self, request):
        """
        用于插入
        """
        res = {}
        session = DBSession_mysql()
        try:
            ReplayMapper.insert_replay_batch(request.data.get("data"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def patch(self, request):
        """
        用于批量重命名
        """
        res = {}
        session = DBSession_mysql()
        try:
            TagRenameMapper.batch_update_col(request.data.get("pks"), request.data.get("item"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))

        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()


class ReplayDelApiView(APIView):
    def delete(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            ReplayMapper.delete_replay(request.data.get("id"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()


class ReplayApiView(APIView):
    """ 复盘数据 """

    def get(self, request):
        session = DBSession_mysql()
        res = {}
        try:
            db_res = ReplayMapper.replay_list(request.query_params.get("date"), session)
            res['data'] = db_res
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args), DateEncoder, False)
        else:
            return JsonResponse(wrapper_res_dict(res, False), DateEncoder, False)
        finally:
            session.close()
            session.commit()

    def put(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            # 注意默认状态
            ctd_obj = from_query_set_get_model(request.data, CodeTagDate)
            ctd_obj.enable = ENABLE
            # 开启标签重命名
            # 这是网页传入的数据，需要设置为默认启用, 对于其他不同的输入源 另说
            ctr_obj = CodeTagRelation(enable=ENABLE)
            ReplayMapper.insert_new_replay(ctd_obj, ctr_obj, session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def delete(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            ReplayMapper.toggle_replay(request.data.get("id"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def patch(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            ReplayMapper.toggle_fresh(request.data.get("id"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()


class SearchCTRKWApiView(APIView):
    """ 搜索方法 """
    def get(self, request):
        res = {}
        try:
            db_res = SearchCTRKWMapper.search_kw_(request.query_params.getlist("kw",["",]))
            res['data'] = db_res
        except Exception as e:
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args), DateEncoder, False)
        else:
            return JsonResponse(wrapper_res_dict(res, False), DateEncoder, False)


class SearchTagsAdviceApiView(APIView):
    """ 搜索方法 """

    def get(self, request):
        res = {}
        try:
            db_res = SearchCTRKWMapper.search_tags(request.query_params.getlist("kw",["",]))
            res['data'] = db_res
        except Exception as e:
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args), DateEncoder, False)
        else:
            return JsonResponse(wrapper_res_dict(res, False), DateEncoder, False)


class CTRBatchInsertOrUpdateApiView(APIView):
    def post(self, request):
        """ 插入数据，删除和增加的 """
        res = {}
        session = DBSession_mysql()
        try:
            delete_ = request.data.get("delete_data")
            append_ = request.data.get("append_data")
            delete_ = [d_ for d_ in delete_ if 'code' in d_]
            append_res = []
            i = 0
            for a_ in append_:
                i += 1
                if a_ == {}:
                    continue
                # session_sub = DBSession_mysql()
                # try:
                    # 子事务， 防止全部数据都不能插入

                ctr_ = set_sqlalchemy_model_values(CodeTagRelation(), a_)
                # 交换值， 因为 tag -> tr.to, origin -> ctr_.tag  传入的tag为变更后的值， origin为原始标签
                ctr_.tag = a_['origin']
                ctr_.enable = ENABLE


                if 'tag' not in a_ or not a_['tag']:
                    a_['tag'] = a_['origin']

                db_res = CodeTagRelationMapper.insert_or_update_relation(ctr_, session, enable_tag=ENABLE, tag_to=a_['tag'],
                                                                rename_enable=ENABLE)
                # append_res.append(db_res)
                if db_res and "uuid" in a_ and "id" not in a_:
                    setattr(db_res, 'uuid', a_['uuid'])
                    append_res.append(db_res)
                    pass

            for d_ in delete_:
                if d_ == {}:
                    continue
                ctr_ = set_sqlalchemy_model_values(CodeTagRelation(), d_)
                # 删除关系， 需要添加del_reason
                if "del_reason" not in d_:
                    raise Exception("缺少删除原因")
                CodeTagRelationMapper.delete_relation(ctr_, session)
            session.commit()
        except Exception as e:
            log.exception(e)
            session.rollback()
            return JsonResponse(generate_message_dict_4_fail(), DateEncoder)
        else:
            # 查找id
            ids_items = []
            for a_ in append_res:
                ids_items.append({"id": a_.id, "uuid":a_.uuid})
            res['append_res'] = ids_items
            return JsonResponse(wrapper_res_dict(res, False), DateEncoder)
        finally:
            session.close()


class CTRFromCodeApiView(APIView):
    def get(self, request):
        res = {}
        try:
            db_res = SearchCTRKWMapper.ctr_from_code(request.query_params.get("kw"))
            res['data'] = db_res
        except Exception as e:
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args), DateEncoder, False)
        else:
            return JsonResponse(wrapper_res_dict(res, False), DateEncoder, False)


class CTRFromTagApiView(APIView):
    def get(self, request):
        res = {}
        try:
            db_res = SearchCTRKWMapper.ctr_from_tag(request.query_params.get("kw"))
            res['data'] = db_res
        except Exception as e:
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(500, e.args), DateEncoder, False)
        else:
            return JsonResponse(wrapper_res_dict(res, False), DateEncoder, False)


class ReplayCheckOutMethodApiView(APIView):
    def post(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            # 删除，添加，修改
            # 删除的数据，包含有表值
            request.data.setdefault("delete",[])
            request.data.setdefault("check",[])
            request.data.setdefault("append",[])
            ban_replay_s = request.data.get("delete")
            checked_data_s = request.data.get("check")
            append_datas = request.data.get('append')
            append_res = []

            # 删除复盘和标签重命名
            ban_replay_and_tr = []
            if "delete_rela_and_tr" in request.data:
                ban_replay_and_tr.extend(request.data.get("delete_rela_and_tr"))
            for idx_, it_ in enumerate(list(ban_replay_s)):
                # ban in _ check
                continue_ = False
                for cd_ in checked_data_s:
                    if cd_['id'] == it_['id']:
                        ban_replay_s.remove(it_)
                        continue_ = True
                        break
                if continue_:
                    continue
                if "delete_flag" in it_ and it_['delete_flag'] == 'tr':
                    ban_replay_s.remove(it_)
                    ban_replay_and_tr.append(it_)
            print(
                "only_ban : {}\n ban_r_tr:{}\n check_data:{}\n".format(ban_replay_s, ban_replay_and_tr, checked_data_s))
            for br_ in ban_replay_s:
                if br_ == {}:
                    continue
                ReplayMapper.ban_replay(br_['id'], session)

            for br_and_tr_ in ban_replay_and_tr:
                if br_and_tr_ == {}:
                    continue
                ReplayMapper.toggle_replay_fresh_2_check(br_and_tr_['id'], session, enable=DISABLE)
                tr_ = TagRename(origin=br_and_tr_['origin'], to=br_and_tr_['tag'], enable=DISABLE)
                TagRenameMapper.insert_or_update_tag_rename(tr_, session, tag_enable=ENABLE, rename_enable=DISABLE)

            # 确认数据时只会进行tag的变更
            for c_d_ in checked_data_s:
                if c_d_ == {}:
                    continue
                ReplayMapper.toggle_replay_fresh_2_check(c_d_['id'], session, enable=ENABLE)
                tr_ = TagRename(origin=c_d_['origin'], to=c_d_['tag'], enable=ENABLE)
                TagRenameMapper.insert_or_update_tag_rename(tr_, session, tag_enable=ENABLE, rename_enable=ENABLE)

            # 新增数据
            # 注意传入的 tag 和 origin意义不同
            for append_data in append_datas:
                new_replay = set_sqlalchemy_model_values(CodeTagDate(), append_data)
                new_replay.tag = append_data['origin']
                ctd_db = ReplayMapper.insert_new_replay(new_replay, CodeTagRelation(enable=ENABLE),session, tag_to=append_data['tag'], )
                if ctd_db and 'uuid' in append_data and 'id' not in append_data:
                    setattr(ctd_db,"uuid", append_data['uuid'])
                    # append_data['id'] = ctd_db.id
                    # del append_data['uuid']
                    append_res.append(ctd_db)


            session.commit()
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            uids = []
            for c_ in append_res:
                uids.append({'uuid':c_.uuid, "id":c_.id})
            res['append_res'] = uids
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.close()

    def get(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            res['data'] = ReplayMapper.select_unchecked_replay()
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))


class ReplayRemoteCrawlApiView(APIView):
    def post(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            # res = request.data.get("replay")
            ctd_obj = from_query_set_get_model(request.data, CodeTagDate)
            # 爬虫不能变更操作， 默认为disable
            ReplayMapper.insert_new_crawl_replay(ctd_obj, CodeTagRelation(enable=ENABLE), session, rename_enable=None, )
            # res = ReplayMapper.pre_parse_replay_batch(request.data.get("data"))
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()


class ReplayBatchApiView(APIView):
    def post(self, request):
        """
        用于前处理
        """
        res = {}
        session = DBSession_mysql()
        try:
            res = ReplayMapper.pre_parse_replay_batch(request.data.get("data"))
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))

        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def put(self, request):
        """
        用于插入
        """
        res = {}
        session = DBSession_mysql()
        try:
            ReplayMapper.insert_replay_batch(request.data.get("data"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()


class TagStatusApiView(APIView):
    # def put(self, request):
    #     res = {}
    #     session = DBSession_mysql()
    #     try:
    #         # 通过网页进行标签的插入
    #         tr_obj = from_query_set_get_model(request.data, TagStatus)
    #         tr_obj.enable = ENABLE
    #         # 设置默认状态
    #         TagStatusMapper.insert_tag_status(tr_obj, session)
    #     except Exception as e:
    #         session.rollback()
    #         log.exception(e)
    #         return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
    #                                                          , e.args))
    #     else:
    #         return JsonResponse(wrapper_res_dict(res, False))
    #     finally:
    #         session.commit()
    def get(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            res_db = TagStatusMapper.list(session)
            res['data'] = parse_sqlalchemy_model_2_dict(res_db)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()

    def patch(self, request):
        res = {}
        session = DBSession_mysql()
        try:
            TagStatusMapper.toggle_tag_status(request.data.get("tag"), session)
        except Exception as e:
            session.rollback()
            log.exception(e)
            return JsonResponse(generate_message_dict_4_fail(status.HTTP_500_INTERNAL_SERVER_ERROR
                                                             , e.args))
        else:
            return JsonResponse(wrapper_res_dict(res, False))
        finally:
            session.commit()
            session.close()


search_col = ['code']

# def query_col_(cols : Iterator, val, ):
